home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / comm / mpmod160.zip / SOURCE.ZIP / Z-TX.C < prev   
C/C++ Source or Header  |  1994-01-01  |  20KB  |  686 lines

  1. /*---------------------------------------------------------------------------*/
  2. /* The send part of the Zmodem protocol.                                     */
  3. /*                                                                           */
  4. /* (C) Copyright M. Jose, 1990 ->                                            */
  5. /* See MPMODEM.DOC for more details about the usage of this source in your   */
  6. /* programs.                                                                 */
  7. /* Written by Mark Jose, Oct-Nov, 1990.                                      */
  8. /*---------------------------------------------------------------------------*/
  9.  
  10. [...]
  11.  
  12. #include "compress.h"
  13.  
  14. [...]
  15. /*
  16.  Private routines
  17. */
  18. [...]
  19. static int  pascal SendData(register BYTE *, register int, int);
  20.  
  21. /*
  22. If you don't have a separate routine to handle crc-16 transfers, then you
  23. will have to create one.
  24.  
  25. Some people implement Zmodem without the ability to run it in CRC-16 mode
  26. because it will always default to the safer CRC-32 mode. This is fine, but
  27. when you want to use it over quite secure lines, CRC-16 is quite adequate.
  28. */
  29. static void pascal SendData16(register BYTE *, register int, int);
  30. static void pascal SendData32(register BYTE *, register int, int);
  31.  
  32. [...]
  33.  
  34.  
  35.  
  36. /*
  37.  SEND BINARY HEADER
  38.  Send ZMODEM binary header hdr of type type
  39. */
  40. static int pascal SendBinaryHeader(int type, BYTE *hdr)
  41. {
  42.     static int n;
  43.  
  44.     BufferByte(ZPAD);
  45.     BufferByte(ZDLE);
  46.  
  47. /*
  48. TxType is the variable that determines the type of transfer. This variable
  49. can change during a file transfer (for hex headers) and must be re-instated
  50. here or else we will have a mix up in the type of transfer mode being used.
  51. TxMaster is determined in the negotiation phase of the transfer. For a
  52. better understanding of its values see that routine (called GetReceiver().)
  53. */
  54.  
  55.     switch(TxType = TxMaster) {
  56. /*
  57. If the TxType is 4 or 3 then the transmission will perhaps involve
  58. compressed data. We must signal the receiver that this is our intention.
  59. We do this by sending either a ZBINC or ZBINC32 frame header.
  60. */
  61.        case 4:
  62.           SendBinaryHeader16(hdr, type, ZBINC);
  63.           break;
  64.        case 3:
  65.           SendBinaryHeader32(hdr, type, ZBINC32);
  66.           break;
  67. /*   ---   */
  68.        case 2:
  69.        default:
  70.           return -1;
  71.        case 1:
  72.           SendBinaryHeader32(hdr, type, ZBIN32);
  73.           break;
  74.        case 0:
  75.           SendBinaryHeader16(hdr, type, ZBIN);
  76.           break;
  77.     }
  78.     n = UnbufferBytes();
  79.     return n;
  80. }
  81.  
  82. /*
  83.  Send binary header with standard CRC-16
  84. */
  85. static void pascal SendBinaryHeader16(BYTE *hdr, int type, int flavour)
  86. {
  87.     static unsigned short crc;
  88.     register int n;
  89.  
  90.     BufferByte(flavour);
  91.  
  92.     ZS_SendByte(type);
  93.  
  94.     crc = Z_UpdateCRC(type, 0);
  95.  
  96.     for (n = 4; --n >= 0;) {
  97.        ZS_SendByte(*hdr);
  98.        crc = Z_UpdateCRC(((unsigned short)(*hdr++ & 0xFF)), crc);
  99.     }
  100.     ZS_SendByte((BYTE ) (crc >> 8));
  101.     ZS_SendByte((BYTE ) crc);
  102.  
  103. }
  104.  
  105. /*
  106.  Send binary header with CRC-32
  107. */
  108. static void pascal SendBinaryHeader32(BYTE *hdr, int type, int flavour)
  109. {
  110.     register int n;
  111.     static ULONG crc;
  112.  
  113.     BufferByte(flavour);
  114.  
  115.     ZS_SendByte(type);
  116.     crc = Z_UpdateCRC32(type, 0xFFFFFFFFL);
  117.  
  118.     for (n = 4; --n >= 0; ) {
  119.        ZS_SendByte(*hdr);
  120.        crc = Z_UpdateCRC32((0xFF & *hdr++), crc);
  121.     }
  122.  
  123.     crc = ~crc;
  124.     for (n = 4; --n >= 0;) {
  125.        ZS_SendByte((int )crc);
  126.        crc >>= 8;
  127.     }
  128. }
  129.  
  130.  
  131.  
  132. /*
  133.  Send binary data in buf (or Compbuff if compressed)
  134. */
  135. static int pascal SendData(register BYTE *buf, register int length, int frameend)
  136. {
  137.     static int n;
  138.     static int comp_lgh;
  139.  
  140. /*
  141. This routine determines which routine we should branch off to depending upon
  142. the type of CRC checking that was negotiated at startup.
  143.  
  144. If the transmission allows for compressed data, then the TxType will be
  145. either 4 or 3. In which case, we will attempt to compress the data into a
  146. block smaller than the "length" passed to us. If this is not possible then
  147. we will send the packet normally.
  148.  
  149. What we do below is determine if the compressed length is smaller than the
  150. length of the uncompressed block. If it is, we flag the transmission as a
  151. "Compressed" transmission and increment the frame-end by 8. For example:
  152.  
  153.      ZCRCE => 'h' => 104 + 8 = 112 => 'p' => ZCRCE_C
  154.      ZCRCG => 'i' => 105 + 8 = 113 => 'q' => ZCRCG_C
  155.      ZCRCQ => 'j' => 106 + 8 = 114 => 'r' => ZCRCQ_C
  156.      ZCRCW => 'k' => 107 + 8 = 115 => 's' => ZCRCW_C
  157.  
  158. This then makes the current frame a compressed frame as well as allowing
  159. us to keep its original status.
  160. */
  161.     if (TxType == 3 || TxType == 4) {
  162.        comp_lgh = Compress(buf, CompBuff, length);
  163.        if (comp_lgh < length) {
  164.           Compressed = 1;
  165.           frameend += 8;    /* Bumps up the frame end to indicate compression */
  166.        } else {
  167.           Compressed = 0;
  168.           comp_lgh = length;
  169.        }
  170.     }
  171.  
  172.  
  173.     switch(TxType) {
  174. /*
  175. Right, now we process the compressed or uncompressed buffer. If the data
  176. was able to be compressed into less space than the uncompressed buffer, then
  177. the "Compressed" flag would have been set to 1 above. In this case, the data
  178. we need to send is contained in "CompBuff". If the data could not be
  179. compressed then "Compressed" would be set to 0 and we will send the data from
  180. the "buf" buffer. Simple, hey?!
  181. */
  182.        case 4:
  183.           SendData16(Compressed ? CompBuff : buf, comp_lgh, frameend);
  184.           break;
  185.        case 3:
  186.           SendData32(Compressed ? CompBuff : buf, comp_lgh, frameend);
  187.           break;
  188. /*   ---   */
  189.        case 2:
  190.        default:
  191.           return ZERROR;
  192.        case 1:
  193.           SendData32(buf, length, frameend);
  194.           break;
  195.        default:
  196.           SendData16(buf, length, frameend);
  197.           break;
  198.     }
  199.     n = UnbufferBytes();
  200. [...]
  201.     return n;
  202.  
  203. }
  204.  
  205. /*
  206.  SEND DATA with 16 bit CRC (and compression if necessary).
  207. */
  208. static void pascal SendData16(register BYTE *buf, register int length, int frameend)
  209. {
  210.    static WORD crc;
  211.    crc = 0;
  212.  
  213.    for (;--length >= 0;) {
  214.       SendByte(*buf);
  215.       crc = UpdateCRC(((WORD )(0xFF & *buf++)), crc);
  216.    }
  217.    BufferByte(ZDLE);
  218.    BufferByte(frameend);
  219.    crc = UpdateCRC(frameend, crc);
  220.    SendByte(crc >> 8);
  221.    SendByte(crc);
  222. }
  223.  
  224.  
  225. /*
  226.  SEND DATA with 32 bit CRC (and compressed if necessary)
  227. */
  228. static void pascal SendData32(register BYTE *buf, register int length, int frameend)
  229. {
  230.    static int c;
  231.    static ULONG crc;
  232.  
  233.    crc = 0xFFFFFFFFL;
  234.    for (;--length >= 0;) {
  235.       c = *buf & 0xFF;
  236.       if ((c & 0140)) {
  237.          BufferByte((lastsent = c));
  238.       } else {
  239.          SendByte(c);
  240.       }
  241.       crc = UpdateCRC32(( (WORD )(*buf++) ), crc);
  242.    }
  243.  
  244.    BufferByte(ZDLE);
  245.    BufferByte(frameend);
  246.    crc = UpdateCRC32(frameend, crc);
  247.    crc = ~crc;
  248.  
  249.    for (length = 4; --length >= 0;) {
  250.       SendByte((int )crc);
  251.       crc >>= 8;
  252.    }
  253. }
  254.  
  255.  
  256.  
  257.  
  258. /*
  259.  Send character c with ZMODEM escape sequence encoding.
  260.  Don't encode special characters if FAST mode is being used.
  261. */
  262. static void pascal SendByte(BYTE ch)
  263. {
  264. /*
  265. Here is the core routine for sending data to the remote without any form of
  266. escape encoding other than for the Zmodem required ZDLE. This means the
  267. transmission can be faster if (for example) you have an 8 bit connect and
  268. no need for software transmission control.
  269. */
  270.  
  271.    if (UsingFast) {
  272.       if ((ch & 0xFF) == ZDLE) {
  273.          BufferByte(ZDLE);
  274.          lastsent = (ZDLE ^ 0x40);
  275.       } else
  276.          lastsent = ch & 0xFF;
  277.  
  278.       BufferByte(lastsent);
  279.       return;
  280.    }
  281.  
  282.    if ((ch & 0x60)) {
  283.       lastsent = ch;
  284.    } else {
  285.      switch (ch & 0x7F) {
  286.          case ZDLE:
  287.          case 16:
  288.          case 17:
  289.          case 19:
  290.             BufferByte(ZDLE);
  291.             lastsent = (ch ^ 0x40);
  292.             break;
  293.          case 13:
  294.             if (ZCtlEsc && ((lastsent & 0x7f) != '@'))
  295.                lastsent = ch;
  296.             else {
  297.                BufferByte(ZDLE);
  298.                lastsent = (ch ^ 0x40);
  299.